<?php

namespace App\Model;

use App\Services\AliPayService;
use App\Services\BspayService;
use App\Services\WechatService;
use Carbon\Carbon;
use Hyperf\Database\Model\Relations\BelongsTo;
use Hyperf\Database\Model\Relations\HasMany;
use Hyperf\Utils\Arr;
use Util\Common;

/**
 * App\PaymentOrder
 *
 * @property int $id
 * @property int $user_id 用户
 * @property int $device_id 用户
 * @property int $fee 金额
 * @property \App\Model\User $user 用户模型
 * @property int $give_fee 退款金额
 * @property string $number 订单号
 * @property string $type 类型
 * @property \Carbon\Carbon|null $paid_at 支付时间
 * @property string $payment_type 支付方式
 * @property array|null $extra 其他信息
 */
class BalanceOrder extends Model
{
    public bool $timestamps = true;
    protected ?string $table = 'balance_orders';


    const STATUS_UNPAID = 0;
    const STATUS_PAID = 1;
    const STATUS_FAILED = 2;
    const STATUS_REFUNDED = 3;

    const USER_SOURCE_TO_PAYMENT_TYPE = [
        User::SOURCE_ALI_PAY => Bill::PAYMENT_TYPE_ALI_PAY,
        User::SOURCE_WE_CHAT => Bill::PAYMENT_TYPE_WE_CHAT_PAY,
    ];


    protected array $guarded = [];

    protected array $casts = [

    ];

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class, 'user_id', 'id');
    }

    public function refund(): HasMany
    {
        return $this->hasMany(RefundBalanceLog::class, 'number', 'number');
    }

    /**充值余额支付后逻辑
     * @param array $params
     * @return void
     */
    public function balanceNotify($data = [])
    {
        $this->status = self::STATUS_PAID;
        $date = \DateTime::createFromFormat('YmdHis', $data['end_time']);
        $this->pay_at = $date->format('Y-m-d H:i:s');
        $this->out_ord_id = $data['out_ord_id'];
        $this->save();
        $this->user->balance += $this->fee;
        $this->user->save();
        $couponCache = "coupon_cache_key" . $this->id;
        if ($this->device_id) {
            $device = Device::where('id', $this->device_id)->first();
            $distributorId = $device->distributor_id;
            $today = date('Y-m-d', time());
            $coupon = Coupon::where('distributor_id', $distributorId)
                ->where('type', Coupon::TYPE_MAP[Coupon::TYPE_RECHARGE_RECEIVE])
                ->where('start_date', '<=', $today)
                ->where('end_date', '>=', $today)
                ->where('is_active', 1)
                ->orderBy('id', 'desc')
                ->first();
            $number = 0;
            if ($coupon) {
                $cacheKey = Coupon::COUPON_MONEY_CACHE . $coupon->id;
                $receiveData = redis()->hGetAll($cacheKey);
                $cacheDevice = Coupon::COUPON_DEVICE_CACHE . $coupon->id;
                $stations = redis()->sMembers($cacheDevice);
                if (!in_array($device->station_id, $stations)) {
                    redis()->setex($couponCache, 60 * 10, 1);
                    return '';
                }
                if ($receiveData) {
                    krsort($receiveData);
                    foreach ($receiveData as $k => $v) {
                        if ($this->fee >= $k) {
                            $number = (int)$v;
                            break;
                        }
                    }
                }
                $insertRecord = [];
                try {
                    for ($i = 0; $i < $number; $i++) {
                        $insertRecord[] = [
                            'coupon_id' => $coupon->id,
                            'user_id' => $this->user_id,
                            'expires_at' => date('Y-m-d H:i:s', time() + (60 * 60 * 24 * $coupon->days)),
                            'device_id' => $device->id,
                            'station_id' => $device->station_id,
                            'created_at' => date('Y-m-d H:i:s', time())
                        ];
                    }
                    CouponRecord::insert($insertRecord);
                } catch (\Exception $e) {
                    echo $e->getMessage();
                }
            }
        }
    }

    public function refundOrder($return_fee)
    {
        $normal = new Normal();
        $return_fee = number_format((float)$return_fee, 2, '.', '');
        if ($this->fee > 0) {
            $save['number'] = $this->number;
            $save['refund_no'] = 'BF' . $normal->randOrder($this->id);
            $save['status'] = 0;
            $save['reject_amt'] = $return_fee;
            $save['type'] = $this->payment_type;
            $save['pay_at'] = $this->pay_at;
            $refund = RefundBalanceLog::create($save);
        }
        try {
            switch ($this->payment_type) {
                //支付宝支付退回
                case Order::WX_PAY:
                    //微信支付退回
                case Order::ALI_PAY:
                    $service = new BspayService();
                    $result = $service->refund($refund,Common::MAIN_HOST.'/user/order/refund_balance_notify');
                    $refund->return_msg = json_encode($result);
                    $refund->save();
                    return $result;
                    break;
                default:
            }
        } catch (\Exception $e) {
            Normal::logger(__METHOD__.'退款代码-save-error--------' . $e->getMessage() . $e->getTraceAsString(), 'order-event');
        }
    }


    public function refundSuccess($params)
    {
        $this->return_fee += $params['actual_ref_amt'];
        $this->save();
        $this->user->balance -= $params['actual_ref_amt'];
        $this->user->save();
    }

}
